package com.nx.platform.es.biz.query.search;

import com.nx.platform.es.biz.wrapper.parser.StatementOperator;
import com.nx.platform.es.common.utils.CommonUtils;
import com.nx.platform.es.entity.response.SearchResult;
import com.alibaba.fastjson.JSON;
import com.nx.platform.es.biz.query.search.cache.SearchCaches;
import com.nx.platform.es.biz.query.search.handler.SearchRequestHandlerChain;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.elasticsearch.action.search.SearchResponse;

import java.util.List;

/**
 * @author
 * @since 2016年10月15日
 */
@Slf4j
public class SearchRequestProcessor {

    private final SearchRequestHandlerChain handlerChain;
    private final SearchCaches searchCaches;

    public SearchRequestProcessor(SearchRequestHandlerChain handlerChain, SearchCaches searchCaches) {
        this.handlerChain = handlerChain;
        this.searchCaches = searchCaches;
    }

    public SearchResult request(SearchRequestContext context) throws Exception {
        // 请求预处理
        handlerChain.handle(context);
        List<String> sizes = context.getQueryTable().get("size", StatementOperator.EQUAL);
        int size = CollectionUtils.isNotEmpty(sizes) ? NumberUtils.toInt(sizes.get(0)) : 0;
        String trace = context.getTrace().toString();
        String cacheKey = CommonUtils.toMD5(trace);
        context.setCacheKey(cacheKey);
        boolean useCache = context.getExpireAfterWrite() > 0 && !context.isFetchSource() && !context.isExplain() && !context.isNocache() && size <= 1000;

        // 尝试取缓存
        if (useCache) {
            SearchResult cached = searchCaches.getCache().get(context.getLogPrefix(), cacheKey);
            if (cached != null) {
                return cached;
            }
        }
        // 取缓存失败时执行ES请求
        SearchResponse response = context.getEsClient().getClient().search(context.getRequest());
        log.info("{} desc=search request={}", context.getLogPrefix(), JSON.toJSONString(context.getRequest()));

        context.setResponse(response);
        SearchResult result = SearchResponses.create(context, response).toSearchResult();

        // 请求结果写入缓存
        if (useCache) {
            searchCaches.getCache().put(context.getLogPrefix(), cacheKey, result, context.getExpireAfterWrite());
        }

        return result;
    }

}
